package com.administrator.scoreManageSys.entity.shiro;

import com.administrator.scoreManageSys.utils.JwtTokenUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.springframework.stereotype.Component;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import java.util.Enumeration;

import static com.administrator.scoreManageSys.system.SystemConstant.*;

/**
 * 基于JWT标准的无状态认证过滤器
 *
 * @author Administrator
 */
@Component
public class JwtFilter extends AccessControlFilter {

    /**
     * 是否允许访问
     */
    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object handler) {
        return null != getSubject(request, response)
                && getSubject(request, response).isAuthenticated();
    }

    /**
     * 拒绝访问
     */
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        //获取token
        String jwtToken = getJwtSubmission(request);
        //当前用户
        Subject subject = getSubject(request, response);
        //当前身份
        AuthenticationToken authenticationToken = null;
        if (jwtToken != null) {
            try {
                authenticationToken = createToken(request, jwtToken);
                //获取当前用户的Id
                String userId = JwtTokenUtils.getUserIdFromToken(jwtToken);
                //设置当前用户
                request.setAttribute(CURRENT_SYSTEM_USER, userId);
                //获取当前用户的角色Id
                Long roleId = JwtTokenUtils.getUserRoleIdFromToken(jwtToken);
                //设置当前用户角色
                request.setAttribute(CURRENT_SYSTEM_USER_ROLE, roleId);
                //设置当前MD5加密随机数
                String randomKey = JwtTokenUtils.getMd5KeyFromToken(jwtToken);
                request.setAttribute(MD5_RANDOM_KEY, randomKey);
                subject.login(authenticationToken);
                return true;
            } catch (Exception e) {
                // token 异常
                throw new RuntimeException("登录失效，请重新登录！");
            }
        }
        // token 不存在
        throw new RuntimeException("未登录，请登录操作！");
    }

    /**
     * 从请求中获取 jwt token
     *
     * @param request 请求
     * @return jwtToken 真正的用户token
     */
    protected String getJwtSubmission(ServletRequest request) {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        //从请求头中jwt token
        String jwtToken = null;
        String authorization = httpServletRequest.getHeader(AUTH);
        if (authorization != null && authorization.startsWith(AUTH_HEAD)) {
            jwtToken = authorization.substring(7);
        }
        return jwtToken;
    }

    /**
     * 创建 AuthenticationToken
     *
     * @param request
     * @return
     */
    protected AuthenticationToken createToken(ServletRequest request, String jwtToken) {
        String host = request.getRemoteHost();
        return new JwtToken(jwtToken, host);
    }

}
